package wci.backend.interpreter.executors;

import static wci.intermediate.icodeimpl.ICodeKeyImpl.ID;
import static wci.intermediate.icodeimpl.ICodeKeyImpl.LINE;
import static wci.intermediate.symtabimpl.SymTabKeyImpl.DATA_VALUE;
import static wci.message.MessageType.ASSIGN;

import java.util.List;

import wci.backend.interpreter.Executor;
import wci.intermediate.ICodeNode;
import wci.intermediate.SymTabEntry;
import wci.message.Message;

/**
 * <h1>AssignmentExecutor</h1>
 *
 * <p>执行一条赋值语句a := b</p>
 *
 * <p>Copyright (c) 2009 by Ronald Mak</p>
 * <p>For instructional purposes only.  No warranties.</p>
 */
public class AssignmentExecutor extends StatementExecutor
{
    public AssignmentExecutor(Executor parent)
    {
        super(parent);
    }
    public Object execute(ICodeNode node)
    {
        //赋值语句有两个子节点，左为存入的目标变量，右为一个表达式。
        List<ICodeNode> children = node.getChildren();
        ICodeNode variableNode = children.get(0);
        ICodeNode expressionNode = children.get(1);

        //计算表达式的值
        ExpressionExecutor expressionExecutor = new ExpressionExecutor(this);
        Object value = expressionExecutor.execute(expressionNode);

        //更改表项的值，注意，这个entry在语法分析的时候已经写入了。
        SymTabEntry variableId = (SymTabEntry) variableNode.getAttribute(ID);
        variableId.setAttribute(DATA_VALUE, value);
        //每个赋值语句一行，发送一条赋值消息
        sendMessage(node, variableId.getName(), value);
        ++executionCount;
        return null;
    }

    /**
     * 发送一条关于此赋值操作结果的消息，什么值在什么行赋给什么变量
     * @param node 赋值语句子树根节点
     * @param variableName 目标变量名称
     * @param value 要赋的值
     */
    private void sendMessage(ICodeNode node, String variableName, Object value)
    {
        Object lineNumber = node.getAttribute(LINE);
        if (lineNumber != null) {
            sendMessage(new Message(ASSIGN, new Object[] {lineNumber,
                                                          variableName,
                                                          value}));
        }
    }
}
